import { compileToFunctions } from "./compiler"
import { callHook, mountComponent } from "./lifecycle"
import { initState } from "./state"
import { mergeOptions } from "./utils"

// 给Vue增加_init方法
export function initMixin (Vue) {
  // 初始化操作
  Vue.prototype._init = function (options) {
    const vm = this
    // 将用户的选项挂载到实例上
    // 定义的全局指令和过滤器等 都会挂载到实例上
    // this 不一定是Vue，也可能是 Sub
    vm.$options = mergeOptions(this.constructor.options, options)

    callHook(vm, 'beforeCreate')
    // 初始化状态，初始化计算属性，watcher
    initState(vm)
    callHook(vm, 'created')

    // options 上存在 el 属性，自动执行 $mount 方法
    if (vm.$options.el) {
      // 调用 $mount 方法，进入挂载阶段
      vm.$mount(vm.$options.el)
    }
  }

  Vue.prototype.$mount = function (el) {
    const vm = this
    const options = vm.$options
    el = document.querySelector(el)
    vm.$el = el
    // render > template > el.outerHTML
    if (!options.render) {
      let template = options.template

      if (!template && el) {
        template = el.outerHTML
      }

      // 对模板进行编译
      const render = compileToFunctions(template)
      // jsx最终会被编译成 h('xxx')
      options.render = render
    }

    mountComponent(vm)
  }
}
